﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Numbers;

namespace System8Equations
{
    /// <summary>
    /// An automatically updating system 8 calculation - whenever something fires, it willl
    /// re-run the calculation.
    /// </summary>
    public class System8UpdatingResults : INotifyPropertyChanged
    {
        private Value n;
        private Value p;
        private Value n1;
        private Value n2;
        private Value p1;
        private Value p2;
        private Value n12;
        private Value p12;

        /// <summary>
        /// Remember the values so we can run the calc when we need to!
        /// </summary>
        /// <param name="n"></param>
        /// <param name="p"></param>
        /// <param name="n1"></param>
        /// <param name="n2"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="n12"></param>
        /// <param name="p12"></param>
        public System8UpdatingResults(Value n, Value p, Value n1, Value n2, Value p1, Value p2, Value n12, Value p12)
        {
            this.n = n;
            this.p = p;
            this.n1 = n1;
            this.n2 = n2;
            this.p1 = p1;
            this.p2 = p2;
            this.n12 = n12;
            this.p12 = p12;

            ///
            /// Create the result values and hook up the prop changed guys
            /// 

            effLTValue = new Value();
            effSLTValue = new Value();
            fakeLTValue = new Value();
            fakeSLTValue = new Value();

            effLTValue.PropertyChanged += (o, a) => OnPropertyChanged("effLT");
            effSLTValue.PropertyChanged += (o, a) => OnPropertyChanged("effSLT");
            fakeLTValue.PropertyChanged += (o, a) => OnPropertyChanged("fakeLT");
            fakeSLTValue.PropertyChanged += (o, a) => OnPropertyChanged("fakeSLT");

            ///
            /// We want to re-run the calc anytime any of those guys change
            /// 

            this.n.PropertyChanged += new PropertyChangedEventHandler(RecalcValues);
            this.n1.PropertyChanged += new PropertyChangedEventHandler(RecalcValues);
            this.n2.PropertyChanged += new PropertyChangedEventHandler(RecalcValues);
            this.n12.PropertyChanged += new PropertyChangedEventHandler(RecalcValues);
            this.p1.PropertyChanged += new PropertyChangedEventHandler(RecalcValues);
            this.p2.PropertyChanged += new PropertyChangedEventHandler(RecalcValues);
            this.p12.PropertyChanged += new PropertyChangedEventHandler(RecalcValues);
            this.p.PropertyChanged += new PropertyChangedEventHandler(RecalcValues);

            ///
            /// Do an inital calculation to make sure we are all in sync
            /// 

            RecalcValues(null, null);
        }

        private Solver _solver = new Solver();

        /// <summary>
        /// Re-run the calculation. Update the results. Then notify anyone listening!
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void RecalcValues(object sender, PropertyChangedEventArgs e)
        {
            var results = _solver.CalculateSystem8(
                n.Val,
                p.Val,
                n1.Val,
                n2.Val,
                p1.Val,
                p2.Val,
                n12.Val,
                p12.Val,
                1.0,
                1.0,
                1.0,
                1.0,
                1.0,
                1.0);

            effLTValue.Val = results.eptag1;
            effSLTValue.Val = results.eptag2;
            fakeLTValue.Val = results.epmistag1;
            fakeSLTValue.Val = results.epmistag2;
        }

        /// <summary>
        /// Fire off an even if anyone is listening
        /// </summary>
        /// <param name="propName"></param>
        private void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        public double effLT { get { return effLTValue.Val; } }

        public double effSLT { get { return effSLTValue.Val; } }

        public double fakeLT { get { return fakeLTValue.Val; } }

        public double fakeSLT { get { return fakeSLTValue.Val; } }

        public Value effLTValue { get; private set; }
        public Value effSLTValue { get; private set; }
        public Value fakeLTValue { get; private set; }
        public Value fakeSLTValue { get; private set; }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}
